{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "bd99c7e6-6f8b-4c77-a602-9d6311ccd1ff",
   "metadata": {},
   "source": [
    "参数有三种类型：路径参数、查询参数和请求体参数。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4b50de71-78de-485b-94e7-40689ae43ab9",
   "metadata": {},
   "source": [
    "如果一个单个参数不是路径中的参数，那么这个参数就会被默认是查询参数。\n",
    "\n",
    "查询参数既可以用get请求，也可以用put请求。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "99436324-0b0b-4d44-9a07-7d5a9ade02ad",
   "metadata": {},
   "source": [
    "## 单个查询参数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "d032aa5e-9255-4463-92de-bcd456aa82b0",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:     Started server process [14976]\n",
      "INFO:     Waiting for application startup.\n",
      "INFO:     Application startup complete.\n",
      "INFO:     Uvicorn running on http://0.0.0.0:8009 (Press CTRL+C to quit)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "INFO:     127.0.0.1:53666 - \"PUT /items/ HTTP/1.1\" 422 Unprocessable Entity\n",
      "INFO:     127.0.0.1:53732 - \"PUT /items/ HTTP/1.1\" 422 Unprocessable Entity\n",
      "INFO:     127.0.0.1:53761 - \"PUT /items/%7Bitem_id%7D HTTP/1.1\" 404 Not Found\n",
      "INFO:     127.0.0.1:53806 - \"PUT /items/ HTTP/1.1\" 422 Unprocessable Entity\n",
      "INFO:     127.0.0.1:53814 - \"PUT /items/ HTTP/1.1\" 422 Unprocessable Entity\n",
      "INFO:     127.0.0.1:53815 - \"PUT /items/ HTTP/1.1\" 422 Unprocessable Entity\n",
      "INFO:     127.0.0.1:53819 - \"PUT /items/ HTTP/1.1\" 422 Unprocessable Entity\n",
      "INFO:     127.0.0.1:54047 - \"PUT /items/ HTTP/1.1\" 422 Unprocessable Entity\n",
      "INFO:     127.0.0.1:54051 - \"PUT /items/ HTTP/1.1\" 422 Unprocessable Entity\n",
      "INFO:     127.0.0.1:54054 - \"PUT /items/ HTTP/1.1\" 422 Unprocessable Entity\n",
      "INFO:     127.0.0.1:54061 - \"PUT /items/ HTTP/1.1\" 422 Unprocessable Entity\n",
      "INFO:     127.0.0.1:54072 - \"PUT /items/ HTTP/1.1\" 422 Unprocessable Entity\n",
      "INFO:     127.0.0.1:54080 - \"PUT /items/?item_id=4 HTTP/1.1\" 200 OK\n",
      "INFO:     127.0.0.1:54087 - \"PUT /items/?item_id=5 HTTP/1.1\" 200 OK\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:     Shutting down\n",
      "INFO:     Waiting for application shutdown.\n",
      "INFO:     Application shutdown complete.\n",
      "INFO:     Finished server process [14976]\n"
     ]
    }
   ],
   "source": [
    "import uvicorn\n",
    "from fastapi import FastAPI\n",
    "app = FastAPI()\n",
    "@app.put(\"/items/\")\n",
    "async def read_item(item_id: int):\n",
    "    return {\"item_id\": item_id}\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    config = uvicorn.Config(app, host='0.0.0.0', port=8009)\n",
    "    server = uvicorn.Server(config)\n",
    "    await server.serve()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "71ca0e93-fecd-4685-93c9-5c9725c322b3",
   "metadata": {},
   "source": [
    "这时你就不能再在浏览器的地址栏里操作了。因为无论你输入什么，都会看到\n",
    "\n",
    "{\"detail\":\"Method Not Allowed\"}\n",
    "\n",
    "那应该如何测试接口呢？可以用fastapi提供的docs界面，可以用requests库，可以用postman软件，可以编写前端页面进行测试等等。\n",
    "\n",
    "我们这里介绍fastapi提供的docs界面和requests库这两种测试方式。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8f25564a-4e94-4467-978c-6325d1c0805d",
   "metadata": {},
   "source": [
    "## fastapi提供的docs界面"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e12fa0fb-027d-4831-93b2-da560315ada8",
   "metadata": {},
   "source": [
    "使用方法非常简单，在根目录输入/docs 即可打开。\n",
    "\n",
    "打开后选中 PUT /items/ 这个接口，打开下拉窗口\n",
    "\n",
    "可以看到 Parameters 是 item_id，而且是 required。\n",
    "\n",
    "然后点击右边的 Try it out\n",
    "\n",
    "在item_id右边的输入框中输入 4 ，点击 Execute\n",
    "\n",
    "会看到 Code 是 200 ，代表成功\n",
    "\n",
    "Response body 是\n",
    "{\r\n",
    "  \"item_id\": 4\r\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2f198eed-8482-48e7-a301-41c45d1ff4a0",
   "metadata": {},
   "source": [
    "## requests库"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9d8fa962-2eee-423b-85ae-9d39126b6cf5",
   "metadata": {},
   "source": [
    "由于jupyter里其中一个格子在运行的时候，其余的格子不能运行，因此在fastapi运行的时候，要想运行其他代码，需要在另外的ipynb文件中执行代码。\n",
    "\n",
    "可以把以下的代码拷贝到另一个ipynb文件中执行。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "43c03643-e162-4047-bb42-6b89e4435afc",
   "metadata": {},
   "outputs": [],
   "source": [
    "import requests\n",
    "url = 'http://127.0.0.1:8009/items/?item_id=5' \n",
    "res = requests.put(url) \n",
    "res.text\n",
    "\n",
    "# 在另一个ipynb文件中运行代码，会得到 '{\"item_id\":5}'"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9a860584-5e59-469b-a999-cf2808be6242",
   "metadata": {},
   "source": [
    "## 多个查询参数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "8f472a15-0d8c-4cba-9dc7-405060f12572",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:     Started server process [14976]\n",
      "INFO:     Waiting for application startup.\n",
      "INFO:     Application startup complete.\n",
      "INFO:     Uvicorn running on http://0.0.0.0:8009 (Press CTRL+C to quit)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "INFO:     127.0.0.1:54159 - \"PUT /items/?item_id=5&name=%E5%BC%A0%E4%B8%89 HTTP/1.1\" 200 OK\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:     Shutting down\n",
      "INFO:     Waiting for application shutdown.\n",
      "INFO:     Application shutdown complete.\n",
      "INFO:     Finished server process [14976]\n"
     ]
    }
   ],
   "source": [
    "import uvicorn\n",
    "from fastapi import FastAPI\n",
    "app = FastAPI()\n",
    "@app.put(\"/items/\")\n",
    "async def read_item(item_id: int, name: str):\n",
    "    return {\"item_id\": item_id, \"name\": name}\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    config = uvicorn.Config(app, host='0.0.0.0', port=8009)\n",
    "    server = uvicorn.Server(config)\n",
    "    await server.serve()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "14be2782-d853-481c-9827-9712a7e948e1",
   "metadata": {},
   "source": [
    "在根目录输入/docs 直接填入 item_id 和 name 右边的输入框即可测试。\n",
    "\n",
    "requests库需要在url中拼接参数："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7c1127fc-e540-4bab-8ab6-3919b03cc17a",
   "metadata": {},
   "outputs": [],
   "source": [
    "url = 'http://127.0.0.1:8009/items/?item_id=5&name=张三' \n",
    "res = requests.put(url) \n",
    "res.text\n",
    "\n",
    "# 在另一个ipynb文件中运行代码，会得到 '{\"item_id\":5,\"name\":\"张三\"}'"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "603a124a-b0da-417b-8ed0-9940d8a1883a",
   "metadata": {},
   "source": [
    "如果一定要把单个参数作为请求体参数。需要使用 Body 指示 FastAPI 将其作为请求体参数。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "73fd0634-b09f-43a3-b5fc-66982462e65b",
   "metadata": {},
   "source": [
    "## 单个请求体参数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "deb919b0-5a3c-467b-9a93-fe717a7e6030",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:     Started server process [14976]\n",
      "INFO:     Waiting for application startup.\n",
      "INFO:     Application startup complete.\n",
      "INFO:     Uvicorn running on http://0.0.0.0:8009 (Press CTRL+C to quit)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "INFO:     127.0.0.1:62083 - \"GET /docs HTTP/1.1\" 200 OK\n",
      "INFO:     127.0.0.1:62083 - \"GET /openapi.json HTTP/1.1\" 200 OK\n",
      "INFO:     127.0.0.1:62082 - \"PUT /items/ HTTP/1.1\" 200 OK\n",
      "INFO:     127.0.0.1:62122 - \"PUT /items/ HTTP/1.1\" 422 Unprocessable Entity\n",
      "INFO:     127.0.0.1:62131 - \"PUT /items/ HTTP/1.1\" 200 OK\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:     Shutting down\n",
      "INFO:     Waiting for application shutdown.\n",
      "INFO:     Application shutdown complete.\n",
      "INFO:     Finished server process [14976]\n"
     ]
    }
   ],
   "source": [
    "import uvicorn\n",
    "from fastapi import Body, FastAPI\n",
    "from typing import Annotated\n",
    "app = FastAPI()\n",
    "@app.put(\"/items/\")\n",
    "async def read_item(item_id: Annotated[int, Body()]):\n",
    "    return {\"item_id\": item_id}\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    config = uvicorn.Config(app, host='0.0.0.0', port=8009)\n",
    "    server = uvicorn.Server(config)\n",
    "    await server.serve()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "acbd9397-85de-4b09-b648-5ac64182eabe",
   "metadata": {},
   "source": [
    "## fastapi提供的docs界面"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "622eaf44-8822-4e15-8b73-f458cd318f38",
   "metadata": {},
   "outputs": [],
   "source": [
    "在根目录输入/docs 即可打开。\n",
    "\n",
    "打开后选中 PUT /items/ 这个接口，打开下拉窗口\n",
    "\n",
    "可以看到 No parameters。\n",
    "\n",
    "然后点击右边的 Try it out\n",
    "\n",
    "在Request body Required下方的大输入框中输入 5 ，点击 Execute\n",
    "\n",
    "会看到 Code 是 200 ，代表成功\n",
    "\n",
    "Response body 是\n",
    "{\n",
    "  \"item_id\": 5\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b77531ac-696e-442a-8058-1098b6480e29",
   "metadata": {},
   "source": [
    "## requests库"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "99380c42-62ba-4e32-bca9-fe6d1b0576a2",
   "metadata": {},
   "outputs": [],
   "source": [
    "import requests\n",
    "url = 'http://127.0.0.1:8009/items/' \n",
    "res = requests.put(url, json=5) \n",
    "res.text\n",
    "\n",
    "# 在另一个ipynb文件中运行代码，会得到 '{\"item_id\":5}'"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3b533b7d-7cef-4e23-a488-ab1dd24f78af",
   "metadata": {},
   "source": [
    "## 多个请求体参数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "664300f5-76ce-4d82-ae81-598d02f56c45",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:     Started server process [14976]\n",
      "INFO:     Waiting for application startup.\n",
      "INFO:     Application startup complete.\n",
      "INFO:     Uvicorn running on http://0.0.0.0:8009 (Press CTRL+C to quit)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "INFO:     127.0.0.1:62352 - \"PUT /items/ HTTP/1.1\" 200 OK\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:     Shutting down\n",
      "INFO:     Waiting for application shutdown.\n",
      "INFO:     Application shutdown complete.\n",
      "INFO:     Finished server process [14976]\n"
     ]
    }
   ],
   "source": [
    "import uvicorn\n",
    "from fastapi import Body, FastAPI\n",
    "from typing import Annotated\n",
    "app = FastAPI()\n",
    "@app.put(\"/items/\")\n",
    "async def read_item(item_id: Annotated[int, Body()], name: Annotated[str, Body()]):\n",
    "    return {\"item_id\": item_id, \"name\": name}\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    config = uvicorn.Config(app, host='0.0.0.0', port=8009)\n",
    "    server = uvicorn.Server(config)\n",
    "    await server.serve()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3761473a-3dfe-481c-a806-736e6978306d",
   "metadata": {},
   "source": [
    "## fastapi提供的docs界面"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7b950db3-d267-4939-9f65-e3fafc35ab1c",
   "metadata": {},
   "outputs": [],
   "source": [
    "在根目录输入/docs 即可打开。\n",
    "\n",
    "打开后选中 PUT /items/ 这个接口，打开下拉窗口\n",
    "\n",
    "可以看到 No parameters。\n",
    "\n",
    "然后点击右边的 Try it out\n",
    "\n",
    "在Request body Required下方的大输入框中输入\n",
    "{\n",
    "  \"item_id\": 5,\n",
    "  \"name\": \"张三\"\n",
    "}\n",
    "\n",
    "点击 Execute\n",
    "\n",
    "会看到 Code 是 200 ，代表成功\n",
    "\n",
    "Response body 是\n",
    "{\n",
    "  \"item_id\": 5,\n",
    "  \"name\": \"张三\"\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "27191325-af84-451f-9a16-38ff74814bff",
   "metadata": {},
   "source": [
    "## requests库"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "36e1fa4d-50e2-40be-b498-b57b22fbf6ff",
   "metadata": {},
   "outputs": [],
   "source": [
    "url = 'http://127.0.0.1:8009/items/' \n",
    "data = {\"item_id\": 5, \"name\": \"张三\"}\n",
    "res = requests.put(url, json=data) \n",
    "res.text\n",
    "\n",
    "# 在另一个ipynb文件中运行代码，会得到 '{\"item_id\":5,\"name\":\"张三\"}'"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0a03ff14-34a7-47b6-bb99-2c594641852d",
   "metadata": {},
   "source": [
    "## 单个Pydantic 模型请求体参数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "511a2f1e-55f5-4cbf-9df3-d0dc75b70811",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:     Started server process [14976]\n",
      "INFO:     Waiting for application startup.\n",
      "INFO:     Application startup complete.\n",
      "INFO:     Uvicorn running on http://0.0.0.0:8009 (Press CTRL+C to quit)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "INFO:     127.0.0.1:54671 - \"POST /items/ HTTP/1.1\" 405 Method Not Allowed\n",
      "INFO:     127.0.0.1:54673 - \"PUT /items/ HTTP/1.1\" 200 OK\n",
      "INFO:     127.0.0.1:54683 - \"PUT /items/ HTTP/1.1\" 200 OK\n",
      "INFO:     127.0.0.1:54707 - \"PUT /items/ HTTP/1.1\" 200 OK\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:     Shutting down\n",
      "INFO:     Waiting for application shutdown.\n",
      "INFO:     Application shutdown complete.\n",
      "INFO:     Finished server process [14976]\n"
     ]
    }
   ],
   "source": [
    "import uvicorn\n",
    "from fastapi import FastAPI\n",
    "from pydantic import BaseModel\n",
    "app = FastAPI()\n",
    "class Item(BaseModel):\n",
    "    name: str\n",
    "    description: str | None = None\n",
    "    price: float\n",
    "    tax: float | None = None\n",
    "@app.put(\"/items/\")\n",
    "async def read_item(item: Item):\n",
    "    return {\"name\":item.name, \"price\":item.price}\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    config = uvicorn.Config(app, host='0.0.0.0', port=8009)\n",
    "    server = uvicorn.Server(config)\n",
    "    await server.serve()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2ec5b755-95d2-4d13-8e2e-901fae47df6f",
   "metadata": {},
   "source": [
    "requests库需要构建字典，传给json这个参数。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2ac5d6f4-fe3f-43a1-aeb3-708b0fc2c39d",
   "metadata": {},
   "outputs": [],
   "source": [
    "url = 'http://127.0.0.1:8009/items/' \n",
    "data = {\"name\": \"细胞生物学\", \"description\": \"考研书籍\", \"price\":35.8, \"tax\":0.6}\n",
    "res = requests.put(url, json=data) \n",
    "res.text\n",
    "\n",
    "# 在另一个ipynb文件中运行代码，会得到 '{\"name\":\"细胞生物学\",\"price\":35.8}'"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "eb707924-3757-49bb-a077-13f52c15c446",
   "metadata": {},
   "source": [
    "## 混合使用 Path、Query 和请求体参数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4dc6ddfd-3b80-401a-aba6-a89d581be328",
   "metadata": {},
   "outputs": [],
   "source": [
    "毫无疑问地，你可以随意地混合使用 Path、Query 和请求体参数声明，FastAPI 会知道该如何处理。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "c00a7745-630e-46b0-bad7-af6df08fc281",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:     Started server process [14976]\n",
      "INFO:     Waiting for application startup.\n",
      "INFO:     Application startup complete.\n",
      "INFO:     Uvicorn running on http://0.0.0.0:8009 (Press CTRL+C to quit)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "INFO:     127.0.0.1:62538 - \"GET /docs HTTP/1.1\" 200 OK\n",
      "INFO:     127.0.0.1:62538 - \"GET /openapi.json HTTP/1.1\" 200 OK\n",
      "INFO:     127.0.0.1:62537 - \"PUT /items/%E5%BC%A0%E4%B8%89?age=18 HTTP/1.1\" 200 OK\n",
      "INFO:     127.0.0.1:62571 - \"PUT /items/%E5%BC%A0%E4%B8%89?age=18 HTTP/1.1\" 200 OK\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:     Shutting down\n",
      "INFO:     Waiting for application shutdown.\n",
      "INFO:     Application shutdown complete.\n",
      "INFO:     Finished server process [14976]\n"
     ]
    }
   ],
   "source": [
    "import uvicorn\n",
    "from fastapi import Body, FastAPI\n",
    "from typing import Annotated\n",
    "app = FastAPI()\n",
    "@app.put(\"/items/{name}\")\n",
    "async def read_item(name: str, age: int, item_id: Annotated[int, Body()]):\n",
    "    return {\"name\": name, \"age\": age, \"item_id\": item_id}\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    config = uvicorn.Config(app, host='0.0.0.0', port=8009)\n",
    "    server = uvicorn.Server(config)\n",
    "    await server.serve()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "42f9a416-ec17-4565-a9f9-dd90035cb071",
   "metadata": {},
   "source": [
    "## requests库"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c18717f0-dbc6-4b0d-86b8-2f80427b0e1c",
   "metadata": {},
   "outputs": [],
   "source": [
    "url = 'http://127.0.0.1:8009/items/张三?age=18' \n",
    "res = requests.put(url, json=5) \n",
    "res.text\n",
    "\n",
    "# 在另一个ipynb文件中运行代码，会得到 '{\"name\":\"张三\",\"age\":18,\"item_id\":5}'"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e8e4cdfc-f068-49f8-8643-542a7eda759a",
   "metadata": {},
   "source": [
    "## 多个Pydantic 模型请求体参数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "9a9ee734-4c05-4d09-a12a-6df6ebf4c307",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:     Started server process [14976]\n",
      "INFO:     Waiting for application startup.\n",
      "INFO:     Application startup complete.\n",
      "INFO:     Uvicorn running on http://0.0.0.0:8009 (Press CTRL+C to quit)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "INFO:     127.0.0.1:62975 - \"PUT /items/ HTTP/1.1\" 200 OK\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:     Shutting down\n",
      "INFO:     Waiting for application shutdown.\n",
      "INFO:     Application shutdown complete.\n",
      "INFO:     Finished server process [14976]\n"
     ]
    }
   ],
   "source": [
    "import uvicorn\n",
    "from fastapi import FastAPI\n",
    "from pydantic import BaseModel\n",
    "app = FastAPI()\n",
    "class Item(BaseModel):\n",
    "    name: str\n",
    "    description: str | None = None\n",
    "    price: float\n",
    "    tax: float | None = None\n",
    "\n",
    "class User(BaseModel):\n",
    "    username: str\n",
    "    full_name: str | None = None\n",
    "@app.put(\"/items/\")\n",
    "async def read_item(item: Item, user: User):\n",
    "    return {\"name\":item.name, \"price\":item.price, \"user\": user}\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    config = uvicorn.Config(app, host='0.0.0.0', port=8009)\n",
    "    server = uvicorn.Server(config)\n",
    "    await server.serve()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7f3ba550-fb4b-4d89-b09e-a50316de6768",
   "metadata": {},
   "source": [
    "在这种情况下，FastAPI 将注意到该函数中有多个请求体参数（两个 Pydantic 模型参数）。\r\n",
    "\r\n",
    "因此，它将使用参数名称作为请求体中的键（字段名称）"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "269719f2-8dc9-4a79-ae8c-c19b74880bd1",
   "metadata": {},
   "source": [
    "## requests库"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1774425f-49e0-4c54-beff-d041d6cacc4b",
   "metadata": {},
   "outputs": [],
   "source": [
    "url = 'http://127.0.0.1:8009/items/' \n",
    "data = {\n",
    "    \"item\":{\"name\": \"细胞生物学\", \"description\": \"考研书籍\", \"price\":35.8, \"tax\":0.6},\n",
    "    \"user\":{\"username\":\"张三\", \"full_name\":\"张三丰\"}\n",
    "}\n",
    "res = requests.put(url, json=data) \n",
    "res.text\n",
    "\n",
    "# 在另一个ipynb文件中运行代码，会得到 \n",
    "# '{\"name\":\"细胞生物学\",\"price\":35.8,\"user\":{\"username\":\"张三\",\"full_name\":\"张三丰\"}}'"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b254d1f3-1afc-46f9-92d7-d49742f36193",
   "metadata": {},
   "source": [
    "## 嵌入单个请求体参数"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "da0614c4-4af4-4000-bb68-501a85e9bd63",
   "metadata": {},
   "source": [
    "假设你只有一个来自 Pydantic 模型 Item 的请求体参数 item。\r\n",
    "\r\n",
    "默认情况下，FastAPI 将直接期望这样的请求体。\r\n",
    "\r\n",
    "但是，如果你希望它期望一个拥有 item 键并在值中包含模型内容的 JSON，就像在声明额外的请求体参数时所做的那样，则可以使用一个特殊的 Body 参数 em\n",
    "\n",
    "item: Item = Body(embed=True)bed："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "470bc0e2-c803-4c9f-b846-ee9f8669c782",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:     Started server process [14976]\n",
      "INFO:     Waiting for application startup.\n",
      "INFO:     Application startup complete.\n",
      "INFO:     Uvicorn running on http://0.0.0.0:8009 (Press CTRL+C to quit)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "INFO:     127.0.0.1:63089 - \"PUT /items/ HTTP/1.1\" 200 OK\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:     Shutting down\n",
      "INFO:     Waiting for application shutdown.\n",
      "INFO:     Application shutdown complete.\n",
      "INFO:     Finished server process [14976]\n"
     ]
    }
   ],
   "source": [
    "import uvicorn\n",
    "from fastapi import FastAPI\n",
    "from pydantic import BaseModel\n",
    "app = FastAPI()\n",
    "class Item(BaseModel):\n",
    "    name: str\n",
    "    description: str | None = None\n",
    "    price: float\n",
    "    tax: float | None = None\n",
    "@app.put(\"/items/\")\n",
    "async def read_item(item: Item = Body(embed=True)):\n",
    "    return {\"name\":item.name, \"price\":item.price}\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    config = uvicorn.Config(app, host='0.0.0.0', port=8009)\n",
    "    server = uvicorn.Server(config)\n",
    "    await server.serve()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d7b2f99a-3a2c-4673-9be3-60c71fee54e0",
   "metadata": {},
   "source": [
    "这时，请求参数的构造需要把item指定为json的一个键，如\n",
    "data = {\r\n",
    "    \"item\":{\"name\": \"细胞生物学\", \"description\": \"考研书籍\", \"price\":35.8, \"tax\":0.6\"}\n",
    "\n",
    "而不是\n",
    "data = {\"name\": \"细胞生物学\", \"description\": \"考研书籍\", \"price\":35.8, \"tax\":0.6}\r\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b9f6b373-0d74-4574-af8d-e80a7bea9393",
   "metadata": {},
   "source": [
    "## requests库"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1fc0ddfe-9ab6-487a-8183-430c21c85e06",
   "metadata": {},
   "outputs": [],
   "source": [
    "url = 'http://127.0.0.1:8009/items/' \n",
    "data = {\n",
    "    \"item\":{\"name\": \"细胞生物学\", \"description\": \"考研书籍\", \"price\":35.8, \"tax\":0.6}\n",
    "}\n",
    "res = requests.put(url, json=data) \n",
    "res.text\n",
    "\n",
    "# 在另一个ipynb文件中运行代码，会得到 '{\"name\":\"细胞生物学\",\"price\":35.8}'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "71a34faf-a23e-42dd-9334-52d2f559a75b",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
